package com.xicode.media.serve.stream;

import cn.hutool.crypto.SecureUtil;
import io.netty.channel.ChannelHandlerContext;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 媒体服务
 *
 * @author LGC
 */
@Component
@RequiredArgsConstructor
public class MediaService {

    private final ThreadPoolExecutor threadPoolExecutor;

    /**
     * 缓存流转换线程
     */
    public static ConcurrentHashMap<String, MediaTransfer> mediaTransferMap = new ConcurrentHashMap<>();


    /**
     * http-flv播放
     */
    public void playForHttp(CameraDTO cameraDto, ChannelHandlerContext ctx) {
        if (mediaTransferMap.containsKey(cameraDto.getMediaKey())) {
            MediaTransfer mediaConvert = mediaTransferMap.get(cameraDto.getMediaKey());
            if (mediaConvert instanceof MediaTransferFlvByJavacv) {
                MediaTransferFlvByJavacv mediaTransferFlvByJavacv = (MediaTransferFlvByJavacv) mediaConvert;
                mediaTransferFlvByJavacv.addClient(ctx, ClientType.HTTP);
            }
        } else {
            MediaTransferFlvByJavacv mediaConvert = new MediaTransferFlvByJavacv(cameraDto);
            mediaTransferMap.put(cameraDto.getMediaKey(), mediaConvert);
            threadPoolExecutor.execute(mediaConvert);
            mediaConvert.addClient(ctx, ClientType.HTTP);
        }
    }

    /**
     * http-flv 关闭播放
     */
    public void closeForHttp(CameraDTO cameraDto, ChannelHandlerContext ctx) {
        if (mediaTransferMap.containsKey(cameraDto.getMediaKey())) {
            MediaTransfer mediaConvert = mediaTransferMap.get(cameraDto.getMediaKey());
            if (mediaConvert instanceof MediaTransferFlvByJavacv) {
                MediaTransferFlvByJavacv mediaTransferFlvByJavacv = (MediaTransferFlvByJavacv) mediaConvert;
                mediaTransferFlvByJavacv.removeClient(ctx, ClientType.HTTP);
            }
        }
    }


    /**
     * ws-flv播放
     */
    public void playForWs(CameraDTO cameraDto, ChannelHandlerContext ctx) {
        if (mediaTransferMap.containsKey(cameraDto.getMediaKey())) {
            MediaTransfer mediaConvert = mediaTransferMap.get(cameraDto.getMediaKey());
            if (mediaConvert instanceof MediaTransferFlvByJavacv) {
                MediaTransferFlvByJavacv mediaTransferFlvByJavacv = (MediaTransferFlvByJavacv) mediaConvert;
                mediaTransferFlvByJavacv.addClient(ctx, ClientType.WEBSOCKET);
            }
        } else {
            MediaTransferFlvByJavacv mediaConvert = new MediaTransferFlvByJavacv(cameraDto);
            mediaTransferMap.put(cameraDto.getMediaKey(), mediaConvert);
            threadPoolExecutor.execute(mediaConvert);
            mediaConvert.addClient(ctx, ClientType.WEBSOCKET);
        }
    }

    /**
     * http-ws 关闭播放
     */
    public void closeForWs(CameraDTO cameraDto, ChannelHandlerContext ctx) {
        if (mediaTransferMap.containsKey(cameraDto.getMediaKey())) {
            MediaTransfer mediaConvert = mediaTransferMap.get(cameraDto.getMediaKey());
            if (mediaConvert instanceof MediaTransferFlvByJavacv) {
                MediaTransferFlvByJavacv mediaTransferFlvByJavacv = (MediaTransferFlvByJavacv) mediaConvert;
                mediaTransferFlvByJavacv.removeClient(ctx, ClientType.WEBSOCKET);
            }
        }
    }

    /**
     * api 开启推流
     */
    public boolean playForApi(CameraDTO cameraDto) {
        String mediaKey = SecureUtil.md5(cameraDto.getUrl());
        cameraDto.setMediaKey(mediaKey);
        cameraDto.setEnabledFlv(true);

        MediaTransfer mediaTransfer = mediaTransferMap.get(cameraDto.getMediaKey());
        if (null == mediaTransfer) {
            MediaTransferFlvByJavacv mediaConvert = new MediaTransferFlvByJavacv(cameraDto);
            mediaTransferMap.put(cameraDto.getMediaKey(), mediaConvert);
            threadPoolExecutor.execute(mediaConvert);
        }

        mediaTransfer = mediaTransferMap.get(cameraDto.getMediaKey());
        //同步等待
        if (mediaTransfer instanceof MediaTransferFlvByJavacv) {
            MediaTransferFlvByJavacv mediaft = (MediaTransferFlvByJavacv) mediaTransfer;
            // 30秒还没true认为启动不了
            for (int i = 0; i < 60; i++) {
                if (mediaft.isRunning() && mediaft.isGrabberStatus() && mediaft.isRecorderStatus()) {
                    return true;
                }
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }
        }
        return false;
    }

    /**
     * api 关闭推流
     */
    public void closeForApi(CameraDTO cameraDto) {
        if (mediaTransferMap.containsKey(cameraDto.getMediaKey())) {
            MediaTransfer mediaConvert = mediaTransferMap.get(cameraDto.getMediaKey());
            if (mediaConvert instanceof MediaTransferFlvByJavacv) {
                MediaTransferFlvByJavacv mediaTransferFlvByJavacv = (MediaTransferFlvByJavacv) mediaConvert;
                mediaTransferFlvByJavacv.setRunning(false);
                mediaTransferMap.remove(cameraDto.getMediaKey());
            }
        }
    }
}
